//============================================================================
// Name        : service.c
// Author      : Jessica Brazelton
// Course	   : CS 6210 Advanced Operating Systems
// Description :
//============================================================================

//================== HEADER FILES ==================
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/types.h>
#include <assert.h>
#include <string.h>
#include <xmlrpc-c/base.h>
#include <xmlrpc-c/server.h>
#include <xmlrpc-c/server_abyss.h>

xmlrpc_env env;
#define MAX_NUM_SERVERS 9
#define RANDPATH "/dev/random"

FILE *fp;
volatile int ch_pid = -1;

static xmlrpc_value* flipCoin(xmlrpc_env*   const envP,
           	   	   	   	   	   	   xmlrpc_value* const paramArrayP,
           	   	   	   	   	   	   void* const serverInfo,
           	   	   	   	   	   	   void* const channelInfo) {
	int fp, ret;
	unsigned int rand;

    if (envP->fault_occurred)
        return NULL;

	/* Return our result. */
    fp = open(RANDPATH, O_RDONLY);
    ret = read(fp, &rand, sizeof(rand));
    return xmlrpc_build_value(envP, "i", rand % 2);
}

void * create_server(void* arg)
{
	xmlrpc_server_abyss_parms * parms = (xmlrpc_server_abyss_parms*) arg;



	printf("Running XML-RPC server %d...\n", parms->port_number );
	xmlrpc_server_abyss(&env, parms, XMLRPC_APSIZE(log_file_name));
}



int main(int argc, char* param[])
{

	struct xmlrpc_method_info3 const methodInfo = {
			/* .methodName     = */ "flipCoin",
	        /* .methodFunction = */ &flipCoin,
	};

	xmlrpc_server_abyss_parms serverparm[MAX_NUM_SERVERS];
	xmlrpc_registry * registryP;

	if(argc<2)
		{
			printf("Invalid number of arguments\n");
			return 0;
		}



	if (strcmp(param[1], "stop")==0)
	{
		fp= fopen("ch_id", "r");  //Doesn't wipe away file
		//fseek(fp, 0,SEEK_SET);
		if(fscanf(fp, "%d", &ch_pid)!=EOF)
		{
			fclose(fp);
			//PRINT_RED;
			printf("My child is gone\n");
			//PRINT_WHITE;
			//printf("REDI will see him in the resurrection\n");
			kill(ch_pid, SIGKILL);
		}
		else
			printf("I have no children\n");

		printf("ch_id= %d", ch_pid);
	}

	else if (strcmp(param[2], "start")==0)
	{
		//TODO: Make sure no other children already alive
		fp= fopen("ch_id", "w+");//Clears file,
		ch_pid = fork();
		if(ch_pid!=0)  //Parent process
		{
			fprintf(fp, "%d", ch_pid);
			fclose(fp);
			printf("Child id = %d\n", ch_pid);
			printf("Exiting\n");
			exit(0);

		}
		else if(ch_pid==0)		//Child process
		{
					// ================== SERVER BEGINS ==================
					//where real work happens
			pthread_t threads[MAX_NUM_SERVERS];
				int port = 8080;
				int i;
				for(i = 0; i < atoi(param[1]); i++) {
					xmlrpc_env_init(&env);
					registryP = xmlrpc_registry_new(&env);
					xmlrpc_registry_add_method3(&env, registryP, &methodInfo);

					serverparm[i].config_file_name = NULL;
					serverparm[i].registryP        = registryP;
					serverparm[i].port_number      = port + i;
					serverparm[i].log_file_name    = "/tmp/xmlrpc_log";
					printf("Starting thread %d", i);
					pthread_create(&threads[i], NULL, create_server, (void*)&serverparm[i]);
					//printf("Running XML-RPC server %d...\n", port + i);
					//xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));
				    /* xmlrpc_server_abyss() never returns */
				} // end for i

				for(i=0;i< atoi(param[1]); i++)
				{
					pthread_join(threads[i],NULL);
				}

		}



	}




	return 0;
} // end main
